UIKeyboardBoundsUserInfoKey è deprecato, cosa usare, invece?
-
25-09-2019 - |
Domanda
Sto lavorando su un app iPad utilizzando 3.2 SDK. Ho a che fare con l'ottenimento delle dimensioni della tastiera per evitare che i miei campi di testo da nascondono dietro di esso.
Ricevo un avviso in Xcode -?> UIKeyboardBoundsUserInfoKey è deprecato cosa devo Non utilizzare invece per ottenere l'avviso
Soluzione
Ho giocato con la soluzione precedentemente offerto, ma ancora avuto problemi. Ecco quello che mi è venuta, invece:
- (void)keyboardWillShow:(NSNotification *)aNotification {
[self moveTextViewForKeyboard:aNotification up:YES];
}
- (void)keyboardWillHide:(NSNotification *)aNotification {
[self moveTextViewForKeyboard:aNotification up:NO];
}
- (void) moveTextViewForKeyboard:(NSNotification*)aNotification up: (BOOL) up{
NSDictionary* userInfo = [aNotification userInfo];
// Get animation info from userInfo
NSTimeInterval animationDuration;
UIViewAnimationCurve animationCurve;
CGRect keyboardEndFrame;
[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
[[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardEndFrame];
// Animate up or down
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:animationDuration];
[UIView setAnimationCurve:animationCurve];
CGRect newFrame = textView.frame;
CGRect keyboardFrame = [self.view convertRect:keyboardEndFrame toView:nil];
newFrame.origin.y -= keyboardFrame.size.height * (up? 1 : -1);
textView.frame = newFrame;
[UIView commitAnimations];
}
Altri suggerimenti
Da documentazione per UIKeyboardBoundsUserInfoKey
:
La chiave per un oggetto NSValue contenente un CGRect che identifica i limiti rettangolo della tastiera in coordinate finestra. Questo valore è sufficiente per ottenere la dimensione della tastiera. Se si desidera ottenere l'origine della tastiera sullo schermo (prima o dopo l'animazione) utilizzare i valori ottenuti dal dizionario informazioni utente attraverso le costanti UIKeyboardCenterBeginUserInfoKey o UIKeyboardCenterEndUserInfoKey. Con il tasto UIKeyboardFrameBeginUserInfoKey o UIKeyboardFrameEndUserInfoKey posto.
Apple raccomanda l'attuazione di una routine di convenienza di questo tipo (che potrebbero essere attuate come categoria aggiunta a UIScreen
):
+ (CGRect) convertRect:(CGRect)rect toView:(UIView *)view {
UIWindow *window = [view isKindOfClass:[UIWindow class]] ? (UIWindow *) view : [view window];
return [view convertRect:[window convertRect:rect fromWindow:nil] fromView:nil];
}
per recuperare proprietà dimensioni dei fotogrammi tastiera window-regolata.
ho preso un approccio diverso, che consiste nel verificare l'orientamento del dispositivo:
CGRect _keyboardEndFrame;
[[notification.userInfo valueForKey:UIKeyboardFrameEndUserInfoKey] getValue:&_keyboardEndFrame];
CGFloat _keyboardHeight = ([[UIDevice currentDevice] orientation] == UIDeviceOrientationPortrait || [[UIDevice currentDevice] orientation] == UIDeviceOrientationPortraitUpsideDown) ? _keyboardEndFrame.size.height : _keyboardEndFrame.size.width;
È sufficiente utilizzare questo codice:
//NSVale *aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
//instead of Upper line we can use either next line or nextest line.
//NSValue *aValue = [info objectForKey:UIKeyboardFrameEndUserInfoKey];
NSValue *aValue = [info objectForKey:UIKeyboardFrameBeginUserInfoKey];
I seguenti correzioni di codice un problema nel di Jay risposta , che presuppone che UIKeyboardWillShowNotification
non scatta di nuovo quando la tastiera è già presenti.
Quando la tipizzazione con il / tastiera cinese giapponese, IOS genera un UIKeyboardWillShowNotification
supplementare con il nuovo telaio tastiera anche se la tastiera è già presente, portando l'altezza del self.textView
essere ridotta una seconda volta nel codice originale.
Questo riduce self.textView
a quasi nulla. Diventa quindi impossibile per recuperare da questo problema in quanto ci sarà solo aspettare un singolo UIKeyboardWillHideNotification
la prossima volta che la tastiera è respinto.
Invece di sottrarre / aggiungere altezza per self.textView
seconda che la tastiera è mostrata / nascosta come nel codice originale, il seguente codice appena calcola l'altezza massima possibile per self.textView
dopo aver sottratto l'altezza della tastiera sullo schermo.
Questo presuppone che self.textView
è supponiamo per riempire l'intera vista del controller della vista, e non c'è altra visualizzazione secondaria che deve essere visibile.
- (void)resizeTextViewWithKeyboardNotification:(NSNotification*)notif {
NSDictionary* userInfo = [notif userInfo];
NSTimeInterval animationDuration;
UIViewAnimationCurve animationCurve;
CGRect keyboardFrameInWindowsCoordinates;
[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
[[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardFrameInWindowsCoordinates];
[self resizeTextViewToAccommodateKeyboardFrame:keyboardFrameInWindowsCoordinates
withAnimationDuration:animationDuration
animationCurve:animationCurve];
}
- (void)resizeTextViewToAccommodateKeyboardFrame:(CGRect)keyboardFrameInWindowsCoordinates
withAnimationDuration:(NSTimeInterval)duration
animationCurve:(UIViewAnimationCurve)curve
{
CGRect fullFrame = self.view.frame;
CGRect keyboardFrameInViewCoordinates =
[self.view convertRect:keyboardFrameInWindowsCoordinates fromView:nil];
// Frame of the keyboard that intersects with the view. When keyboard is
// dismissed, the keyboard frame still has width/height, although the origin
// keeps the keyboard out of the screen.
CGRect keyboardFrameVisibleOnScreen =
CGRectIntersection(fullFrame, keyboardFrameInViewCoordinates);
// Max frame availble for text view. Assign it to the full frame first
CGRect newTextViewFrame = fullFrame;
// Deduct the the height of any keyboard that's visible on screen from
// the height of the text view
newTextViewFrame.size.height -= keyboardFrameVisibleOnScreen.size.height;
if (duration)
{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve:curve];
}
// Adjust the size of the text view to the new one
self.textView.frame = newTextViewFrame;
if (duration)
{
[UIView commitAnimations];
}
}
Inoltre, non dimenticare di registrare le notifiche della tastiera in viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
NSNotificationCenter* notifCenter = [NSNotificationCenter defaultCenter];
[notifCenter addObserver:self selector:@selector(resizeTextViewWithKeyboardNotification:) name:UIKeyboardWillShowNotification object:nil];
[notifCenter addObserver:self selector:@selector(resizeTextViewWithKeyboardNotification:) name:UIKeyboardWillHideNotification object:nil];
}
Informazioni sulla divisione del codice di ridimensionamento in due parti
Il motivo per cui il ridimensionamento textView codice è diviso in due parti (resizeTextViewWithKeyboardNotification:
e resizeViewToAccommodateKeyboardFrame:withAnimationDuration:animationCurve:
) è di fissare un altro problema quando i persiste tastiera attraverso una trasmissione da un controllore vista all'altra (vedere Come faccio a rilevare la tastiera iOS quando rimane tra controllori? ).
Poiché la tastiera è già presente prima che il controllore visualizzazione viene spinto, non c'è nessuna notifica tastiera aggiuntivi vengono generati dal IOS, e quindi non c'è modo per ridimensionare il textView
basato su tali notifiche tastiera.
Il codice sopra (così come il codice originale) che ridimensiona self.textView
sarà quindi solo lavoro quando viene mostrata la tastiera dopo la vista è stato caricato.
La mia soluzione è quella di creare un Singleton che memorizza le ultime coordinate da tastiera, e sul - viewDidAppear:
del viewController, chiamata:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
// Resize the view if there's any keyboard presence before this
// Only call in viewDidAppear as we are unable to convertRect properly
// before view is shown
[self resizeViewToAccommodateKeyboardFrame:[[UASKeyboard sharedKeyboard] keyboardFrame]
withAnimationDuration:0
animationCurve:0];
}
UASKeyboard
è il mio Singleton qui. Idealmente dovremmo chiamare questo - viewWillAppear:
, tuttavia nella mia esperienza (almeno su iOS 6), il metodo convertRect:fromView:
che dobbiamo utilizzare in resizeViewToAccommodateKeyboardFrame:withAnimationDuration:animationCurve:
non converte correttamente la tastiera cornice alle coordinate vista prima la vista è completamente visibile.
Basta usare il tasto UIKeyboardFrameBeginUserInfoKey
o UIKeyboardFrameEndUserInfoKey
invece di UIKeyboardBoundsUserInfoKey
@ Jason, è il codice se bene, tranne per un punto.
Al momento non sono in realtà animando nulla e la vista sarà semplicemente `pop' al suo nuovo size.height.
È necessario specificare uno stato da cui partire per animare. L'animazione è una sorta di (da stato) -. Cosa> (allo stato)
Fortunatamente esiste un metodo molto conveniente per specificare lo stato attuale della vista come (dallo stato).
[UIView setAnimationBeginsFromCurrentState:YES];
Se si aggiunge che la linea subito dopo beginAnimations: contesto: il codice funziona perfettamente.
- (CGSize)keyboardSize:(NSNotification *)aNotification {
NSDictionary *info = [aNotification userInfo];
NSValue *beginValue = [info objectForKey:UIKeyboardFrameBeginUserInfoKey];
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
CGSize keyboardSize;
if ([UIKeyboardDidShowNotification isEqualToString:[aNotification name]]) {
_screenOrientation = orientation;
if (UIDeviceOrientationIsPortrait(orientation)) {
keyboardSize = [beginValue CGRectValue].size;
} else {
keyboardSize.height = [beginValue CGRectValue].size.width;
keyboardSize.width = [beginValue CGRectValue].size.height;
}
} else if ([UIKeyboardDidHideNotification isEqualToString:[aNotification name]]) {
// We didn't rotate
if (_screenOrientation == orientation) {
if (UIDeviceOrientationIsPortrait(orientation)) {
keyboardSize = [beginValue CGRectValue].size;
} else {
keyboardSize.height = [beginValue CGRectValue].size.width;
keyboardSize.width = [beginValue CGRectValue].size.height;
}
// We rotated
} else if (UIDeviceOrientationIsPortrait(orientation)) {
keyboardSize.height = [beginValue CGRectValue].size.width;
keyboardSize.width = [beginValue CGRectValue].size.height;
} else {
keyboardSize = [beginValue CGRectValue].size;
}
}
return keyboardSize;
}
Ecco un buon dettagli http: // i-phone -dev.blogspot.com/2012/01/different-way-to-show-keyboard-and.html
La sua funzionava così
Questo è il vincolo della Sava fondo pulsante
@IBOutlet weak var saveBtnBottom: NSLayoutConstraint!
@IBOutlet weak var nameText: UITextField!
All'interno viewDidLoad
NotificationCenter.default.addObserver(self, selector: #selector(keyBoardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyBoardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
nameText.delegate = self
Questa è le funzioni di cui abbiamo bisogno
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
nameText.resignFirstResponder()
return true
}
@objc func keyBoardWillShow(notification: Notification){
if let userInfo = notification.userInfo as? Dictionary<String, AnyObject>{
let frame = userInfo[UIResponder.keyboardFrameEndUserInfoKey]
let keyBoardRect = frame?.cgRectValue
if let keyBoardHeight = keyBoardRect?.height {
self.saveBtnBottom.constant = keyBoardHeight
UIView.animate(withDuration: 0.5, animations: {
self.view.layoutIfNeeded()
})
}
}
}
@objc func keyBoardWillHide(notification: Notification){
self.saveBtnBottom.constant = 30.0
UIView.animate(withDuration: 0.5, animations: {
self.view.layoutIfNeeded()
})
}